home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1997
/
MacHack 1997.toast
/
Hacks
/
Hacks ’97
/
WhereTheHellWasIReading?
/
source code
/
WhereTheHellINIT.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-06-28
|
9KB
|
318 lines
// hi there
// Copyright © 1997 Pierre Houston. All rights reserved.
// or something like that
// Portions copied from RandomFinderStrings, Mike Scanlin. 24 Jan 1993
#ifndef __TYPES__
# include <Types.h>
#endif
#ifndef __QUICKDRAW__
# include <Quickdraw.h>
#endif
#ifndef __OSUTILS__
# include <OSUtils.h>
#endif
#ifndef __WINDOWS__
# include <Windows.h>
#endif
#ifndef __MEMORY__
# include <Memory.h>
#endif
#ifndef __LOWMEM__
# include <LowMem.h>
#endif
#include "ShowInitIcon.h"
#define rLoadBadIcon 128
#define rLoadOKIcon1 129
#define rLoadOKIcon2 130
#define rLoadOKIcon3 131
#define rLoadOKIcon4 132
#define rLoadOKIcon5 133
#define rLoadOKIcon6 134
#define rLoadOKIcon7 135
typedef pascal void (*ScrollRectProcPtr)(const Rect *r, short dh, short dv, RgnHandle rgn);
struct PatchGlobals {
ScrollRectProcPtr oldScrollRect;
RgnHandle savedClipRgn;
RgnHandle tempRgn;
unsigned long flags;
};
typedef struct PatchGlobals PatchGlobals, *PatchGlobalsPtr;
#define HACKOFF 1
#define HACKMOREOFTEN 2
#define INVERTHACKRECTS 3
pascal void MyScrollRect(const Rect *r, short dh, short dv, RgnHandle rgn);
void FibonacciScrollMagic(short a, short b, short sum, short count, Boolean up, const Rect *r, GrafPtr pPort);
void StartPatchCode(void);
void EndPatchCode(void);
pascal void main()
{
// anyone know how to make a fat patch??
Ptr patchPtr;
PatchGlobalsPtr pgPtr;
long codeSize, offset;
long time;
/* try and get some memory in the system heap
* for code and globals */
codeSize = (long) EndPatchCode - (long) StartPatchCode;
patchPtr = NewPtrSys(codeSize + sizeof(PatchGlobals));
if (!patchPtr)
return; /* out of memory--abort patching */
/* initialize the patch globals at the
* beginning of the block */
pgPtr = (PatchGlobalsPtr) patchPtr;
pgPtr->oldScrollRect = (ScrollRectProcPtr) NGetTrapAddress(_ScrollRect, ToolTrap);
// alloc a region first time we hit our patch
pgPtr->savedClipRgn = 0L;
pgPtr->tempRgn = 0L;
pgPtr->flags = 0;
/* move the code into place after the globals */
BlockMove(StartPatchCode, patchPtr + sizeof(PatchGlobals), codeSize);
/* set the patches */
patchPtr += sizeof(PatchGlobals);
offset = (long) MyScrollRect - (long) StartPatchCode;
NSetTrapAddress((UniversalProcPtr) (patchPtr + offset), _ScrollRect, ToolTrap);
// call ShowInitIcon
ShowInitIcon(rLoadOKIcon1, false);
Delay(26, &time);
ShowInitIcon(rLoadOKIcon2, false);
Delay(12, &time);
ShowInitIcon(rLoadOKIcon3, false);
Delay(12, &time);
ShowInitIcon(rLoadOKIcon4, false);
Delay(15, &time);
ShowInitIcon(rLoadOKIcon5, false);
Delay(18, &time);
ShowInitIcon(rLoadOKIcon6, false);
Delay(20, &time);
ShowInitIcon(rLoadOKIcon7, true);
{
Str255 str;
KeyMap keys;
GetKeys(keys);
if (keys[1] & 0x8)
{
pgPtr->flags |= HACKOFF; // turn hack off
NumToString((long) &pgPtr->flags, &str[5]);
*(unsigned long*) &str[1] = ';dl '; // prepend ';dl ' to string
str[0] = str[5] + 5;
str[5] = '#';
DebugStr(str);
}
}
}
void StartPatchCode()
{
}
pascal void MyScrollRect(const Rect *r, short dh, short dv, RgnHandle rgn)
{
PatchGlobalsPtr pgPtr;
GrafPtr pPort;
short scrollDistance;
short fontHeight;
ControlHandle windowControl;
int windowControlDistance;
Boolean doAnim = false;
Rect tempRect;
/* find our globals */
pgPtr = (PatchGlobalsPtr) ((long) StartPatchCode - sizeof(PatchGlobals));
if (!(pgPtr->flags & HACKOFF))
{
GetPort(&pPort);
fontHeight = 16; // %%% HACK! :-)
scrollDistance = dv < 0 ? -dv : dv;
// how do we tell its a document paging down?
// if the port is the frontmost window and rect is about the size of a vertical scrollbar
// in the window and its scrolling vertically more than a couple lines of text, and less
// than almost the entire height
if (!dh && pPort == FrontWindow()
&& scrollDistance <= r->bottom - r->top - fontHeight
&& (pgPtr->flags & HACKMOREOFTEN || scrollDistance >= fontHeight * 3))
{
#if 0
// look for a vertical scrollbar in the window
// if we don't do this, then maybe the app, for example, is scrolling down a portion of
// the visible document while its inserting another line
windowControl = ((WindowPeek) pPort)->controlList;
while (windowControl)
{
// if correct width and at least the minimum height, it might be a scroll bar
if (tempRect.right - tempRect.left == 16 && tempRect.bottom - tempRect.top >= 48)
{
// if control is nearly right beside the scroll rect, lets just say it probably is
// a scroll bar and we'll do the scrolling animation (woohoo)
tempRect = (**windowControl).contrlRect;
windowControlDistance = tempRect.left - r->right;
if ((windowControlDistance < 0 ? -windowControlDistance : windowControlDistance) < 3)
{
doAnim = true;
break;
}
}
windowControl = (**windowControl).nextControl;
}
if (!doAnim) SysBeep(10);
#else
doAnim = true;
#endif
}
}
if (doAnim)
{
// do the animation
FibonacciScrollMagic(0, 1, 1, scrollDistance, dv < 0, r, pPort);
// clip out the destination rect so the real ScrollRect doesn't scroll it again
if (!pgPtr->savedClipRgn)
pgPtr->savedClipRgn = NewRgn();
if (!pgPtr->tempRgn)
pgPtr->tempRgn = NewRgn();
CopyRgn(pPort->clipRgn, pgPtr->savedClipRgn);
RectRgn(pgPtr->tempRgn, r);
OffsetRgn(pgPtr->tempRgn, 0, dv);
DiffRgn(pPort->clipRgn, pgPtr->tempRgn, pPort->clipRgn);
if (pgPtr->flags & INVERTHACKRECTS)
{
long time;
InvertRect(&tempRect);
Delay(30, &time);
InvertRect(&tempRect);
InvertRgn(pPort->clipRgn);
Delay(30, &time);
InvertRgn(pPort->clipRgn);
}
/* call the real ScrollRect */
(*pgPtr->oldScrollRect)(r, dh, dv, rgn);
// restore the clip region
CopyRgn(pgPtr->savedClipRgn, pPort->clipRgn);
}
else
{
/* call the real ScrollRect */
(*pgPtr->oldScrollRect)(r, dh, dv, rgn);
}
}
void FibonacciScrollMagic(short a, short b, short sum, short count, Boolean up, const Rect *r, GrafPtr pPort)
{
if (sum + a + b >= count)
{
// the next recursion would be too far, so exit the recursion and start scrolling
// scroll by b pixels plus the remainder
// (scrolling only b pixels & returning will end up scrolling an offset equal to sum
// so the remainder is the amount that would be left over: count - sum)
b += count - sum;
sum = count;
}
else
{
// we will scroll b pixels
// do the scroll for this iteration last, so the largest amount is scrolled first
FibonacciScrollMagic(b, a + b, sum + a + b, count, up, r, pPort);
}
// begin another block here so the compiler can guess not to leave stack space for these
// local vars during all that recursion above. if we do leave this stack space before the
// recursion, then theres space left at every iteration. waste stack not or want stack not.
{
// pick the pixels to scroll this iteration
// we also have to erase the pixels that are left behind
// sum is the number of pixels this and earlier iterations will scroll in total
// so the offset that has already been scrolled should be count - sum
// use this info do we don't have to scroll pixels already erased in past iterations
Rect rDst;
Rect rSrc = *r;
Rect rWake; // ie. the pixels in our wake
if (up)
{
rSrc.top += b; // pixels up here would get copied up out of portRect
rSrc.bottom -= count - sum; // pixels down here have already been erased
rDst = rSrc;
OffsetRect(&rDst, 0, -b); // negative value to offset coordinates up
rWake = rSrc;
rWake.top = rDst.bottom; // erase the pixels that won't get copied over
}
else
{
rSrc.top += count - sum; // pixels up here have already been erased
rSrc.bottom -= b; // pixels down here would get copied down out of portRect
rDst = rSrc;
OffsetRect(&rDst, 0, b); // positive value to offset coordinates down
rWake = rSrc;
rWake.bottom = rDst.top; // erase the pixels that won't get copied over
}
CopyBits(&pPort->portBits, &pPort->portBits, &rSrc, &rDst, srcCopy, NULL);
EraseRect(&rWake);
#if 0
if (!a)
{
long time;
/*InvertRect(&rSrc);
Delay(6, &time);
InvertRect(&rSrc);
Delay(15, &time);*/
InvertRect(&rDst);
Delay(6, &time);
InvertRect(&rDst);
/*Delay(15, &time);
InvertRect(&rWake);
Delay(6, &time);
InvertRect(&rWake);*/
Delay(20, &time);
}
#endif
// if this happens to be the first iteration, we will never scroll a pixels
// thats why the caller should call the first iteration with a=0, b=1
}
}
void EndPatchCode()
{
}